//package com.huidu.bitrade.filter;
//
//import cn.hutool.json.JSONUtil;
//import com.huidu.bitrade.exception.ServiceException;
//import com.huidu.bitrade.util.CSRFFilterConfigUtils;
//import lombok.SneakyThrows;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang.StringUtils;
//import org.springframework.context.annotation.Configuration;
//import javax.servlet.*;
//import javax.servlet.annotation.WebFilter;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.IOException;
//import java.net.URL;
//
//
//@WebFilter(urlPatterns = "/*",filterName = "csrfFilter")
//@Configuration
//@Slf4j
//public class CsrfFilter implements Filter {
//
//
//    @Override
//    public void init(FilterConfig filterConfig) throws ServletException {
//
//    }
//
//    /**
//     * @param servletRequest
//     * @param servletResponse
//     * @param filterChain
//     * @description 执行CRSF过滤操作
//     */
//    @SneakyThrows
//    @Override
//    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//        HttpServletRequest req = (HttpServletRequest) servletRequest;
//        HttpServletResponse res = (HttpServletResponse) servletResponse;
//        // 判断CSRF防护是否开启，如果没开启则直接略过过滤操作
//        if (!CSRFFilterConfigUtils.getOpenCsrfProtect()) {
//            filterChain.doFilter(servletRequest, servletResponse);
//        } else {
//            String referer = req.getHeader("Referer");
//            if (!StringUtils.isBlank(referer)) {
//                // 获取Referer参数中的地址和端口
//                String refererHostAndPort = getHostAndPort(req,referer);
//                // 获取RequestURL参数中的地址和端口
//                String requestHostAndPort = getHostAndPort(req,null);
//                // 同域名和同端口，即同一个域的系统，通过
//                if (requestHostAndPort.equalsIgnoreCase(refererHostAndPort)) {
//                    filterChain.doFilter(servletRequest, servletResponse);
//                }else {
//                    // 如果不同域名或端口，继续判断域名是否在白名单中，如果在白名单中则通过
//                    if(isCsrfWhiteDomains(refererHostAndPort)) {
//                        filterChain.doFilter(servletRequest, servletResponse);
//                        return;
//                    }
//                    // 获取RequestURL参数中的路径信息
//                    String path = new URL(req.getRequestURL().toString()).getPath();
//                    log.info("request请求路径 path = " + path);
//                    // 将路径中的域名去除，只保留具体路径
//                    String actionPath = path.replaceAll(servletRequest.getServletContext().getContextPath(), "");
//                    // 判断路径是否在访问路径白名单中，如果在白名单中，则通过，继续后续执行
//                    if(isCsrfWhitePaths(actionPath)) {
//                        filterChain.doFilter(servletRequest, servletResponse);
//                        return;
//                    }
//                    log.warn("csrf跨站点伪造请求已经被拦截：");
//                    log.warn("requestURL = " + req.getRequestURL().toString());
//                    log.warn("referer = " + referer);
//                    res.sendRedirect(req.getContextPath() + "/illegal");
//                    return;
////                    throw new ServiceException("客户端网络异常！");
//                }
//            }else{
//                filterChain.doFilter(servletRequest, servletResponse);
//            }
//        }
//    }
//
//    /**
//     * @param request
//     * @param referer
//     * @return java.lang.String
//     * @description 获取请求地址和端口
//     */
//    protected String getHostAndPort(HttpServletRequest request, String referer) throws IOException {
//        URL url;
//        if (StringUtils.isNotEmpty(referer)) {
//            url = new URL(referer);
//        } else {
//            url = new URL(request.getRequestURL().toString());
//        }
//        String requestHostAndPort;
//        if(url.getPort() == -1) {
//            requestHostAndPort = url.getHost();
//        }else {
//            requestHostAndPort = url.getHost() + ":" + url.getPort();
//        }
//        return requestHostAndPort;
//
//    }
//
//    @Override
//    public void destroy() {
//
//    }
//
//    /**
//     * @param path
//     * @return boolean
//     * @description 判断请求路径是否在路径白名单中
//     */
//    private boolean isCsrfWhitePaths(String path) {
//        if(CSRFFilterConfigUtils.getCsrfWhitePaths() != null && CSRFFilterConfigUtils.getCsrfWhitePaths().length > 0) {
//            for (String csrfWhitePath : CSRFFilterConfigUtils.getCsrfWhitePaths()) {
//                if(!StringUtils.isBlank(csrfWhitePath)) {
//                    if(csrfWhitePath.equals(path)) {
//                        log.info("跨站点请求所有路径白名单：csrfWhitePaths = " + JSONUtil.toJsonStr(CSRFFilterConfigUtils.getCsrfWhitePaths()));
//                        log.info("符合跨站点请求路径白名单：path = " + path);
//                        return true;
//                    }
//                }
//            }
//        }
//        return false;
//    }
//
//    /**
//     * @param refererHostAndPort
//     * @return boolean
//     * @description 判断请求域名是否在域名白名单中
//     */
//    private boolean isCsrfWhiteDomains(String refererHostAndPort) {
//        if(CSRFFilterConfigUtils.getCsrfWhiteDomains() != null && CSRFFilterConfigUtils.getCsrfWhiteDomains().length > 0) {
//            for (String csrfWhiteDomain : CSRFFilterConfigUtils.getCsrfWhiteDomains()) {
//                if(!StringUtils.isBlank(csrfWhiteDomain)) {
//                    if(csrfWhiteDomain.equals(refererHostAndPort)) {
//                        log.info("跨站点请求所有【域名】]白名单：csrfWhiteDomains = " + JSONUtil.toJsonStr(CSRFFilterConfigUtils.getCsrfWhiteDomains()));
//                        log.info("符合跨站点请求【域名】白名单：refererHost = " + refererHostAndPort);
//                        return true;
//                    }
//                }
//            }
//            log.info("跨站点请求非法【域名】：refererHost = " + refererHostAndPort);
//        }
//        return false;
//    }
//}
